import { createPermission, deletePermission, getPermissionList, updatePermission } from "@/api/permission";
import { formatFormItem, FormItemType, FormTableItemType } from "@/components/FormByData/FormByData";
import Table, { TableRef } from "@/components/Table";
import { Card, Space, Button, message, FormInstance, Tag } from "antd";
import { ComponentType, Key, MutableRefObject, useMemo, useRef, useState } from "react";
import { formatDate } from "@/utils/date";
import { CopyOutlined, EditOutlined, FileAddOutlined, MinusOutlined, PlusOutlined } from "@ant-design/icons";
import FormByData from "@/components/FormByData/FormByData";
import { CreatePermissionReq, Permission as PermissionType, UpdatePermissionReq } from "@/typings/api/permission";
import Search from "@/components/Search";
import Modal from "@/components/Modal/Modal";
import DictionaryColumnRender from "@/components/DictionaryColumnRender";
import { Method, permissionTypeOptions } from "@/constant/permission";
import IconSelect from "@/components/IconSelect";
import * as icons from "@ant-design/icons";
import { AntdIconProps } from "@ant-design/icons/lib/components/AntdIcon";

type SearchFields = Pick<PermissionType, "name" | "key" | "type">;
const OperationMap = {
    add: "添加",
    edit: "编辑",
    addChild: "添加子权限",
    clone: "克隆",
};

const Permission = () => {
    const [showParentName, setShowParentName] = useState(false);
    const columns = useMemo<FormTableItemType<UpdatePermissionReq>[]>(
        () => [
            { dataIndex: "parentName", title: "父级权限", componentProps: { readOnly: true }, isTable: false, isForm: showParentName },
            { dataIndex: "name", title: "权限名", required: true, minWidth: 190 },
            { dataIndex: "key", title: "权限标识", required: true },
            {
                dataIndex: "type",
                title: "权限类型",
                dictType: "permissionType",
                dictClass: "string",
                options: permissionTypeOptions,
                render(value) {
                    return <DictionaryColumnRender dictType="permissionType" value={value} />;
                },
                type: "select",
                required: true,
                minWidth: 90,
            },
            {
                dataIndex: "method",
                title: "请求方法",
                type: "select",
                options: Method.map(value => ({ label: value, value })),
                render: value => value && <Tag>{value}</Tag>,
            },
            { dataIndex: "path", title: "页面链接/接口地址", minWidth: 150 },
            { dataIndex: "label", title: "页面名称" },
            { dataIndex: "component", title: "组件地址" },
            {
                dataIndex: "icon",
                minWidth: 90,
                title: "菜单图标",
                component: IconSelect,
                componentProps: { allowClear: true },
                align: "center",
                render: value => {
                    if (!value) return "";
                    const Icon = icons[value as keyof typeof icons] as ComponentType<AntdIconProps>;
                    return <Icon className="mr-2" />;
                },
            },
            { dataIndex: "children", title: "子权限", isForm: false, isTable: false },
            {
                dataIndex: "status",
                title: "状态",
                dictType: "status",
                dictClass: "boolean",
                render: (value: boolean) => <DictionaryColumnRender dictType="status" value={value} />,
                type: "radio",
                minWidth: 70,
            },
            {
                dataIndex: "sort",
                title: "排序",
                type: 'inputNumber',
            },
            { dataIndex: "desc", title: "描述" },
            { dataIndex: "createdAt", title: "创建时间", render: (val: string) => formatDate(val), isForm: false },
            { dataIndex: "updatedAt", title: "更新时间", render: (val: string) => formatDate(val), isForm: false },
            { dataIndex: "operation", isForm: false, title: "操作", fixed: "right" },
        ],
        [showParentName]
    );

    const [modalShow, setModalShow] = useState(false);
    const [opType, setOpType] = useState<"add" | "edit" | "addChild" | "clone">("add");
    const currentRecord = useRef<UpdatePermissionReq>();
    const permissions = useRef<PermissionType[]>([]);
    const getParent = () => {
        let res: PermissionType | undefined;
        const loop = (list: PermissionType[], parent?: PermissionType) => {
            list.some(item => {
                if (item._id === currentRecord.current?._id) {
                    res = parent;
                    return true;
                } else {
                    res = loop((item.children || []) as PermissionType[], item);
                    if (res) return true;
                }
            });
            return res;
        };
        return loop(permissions.current);
    };

    const handleAdd = () => {
        setOpType("add");
        setShowParentName(false);
        setModalShow(true);
        formRef.current?.resetFields();
    };

    const clickEdit = (record: UpdatePermissionReq) => {
        setOpType("edit");
        currentRecord.current = record;
        const parentName = getParent()?.name;
        setShowParentName(!!parentName);
        setModalShow(true);
        formRef.current?.resetFields();
        formRef.current?.setFieldsValue({ parentName, ...record });
    };

    const clickAddChild = (record: UpdatePermissionReq) => {
        setOpType("addChild");
        setShowParentName(true);
        setModalShow(true);
        formRef.current?.resetFields();
        formRef.current?.setFieldsValue({ parentName: record.name });
        currentRecord.current = record;
    };

    const clickClone = (record: UpdatePermissionReq) => {
        setOpType("clone");
        currentRecord.current = record;
        const parentName = getParent()?.name;
        setShowParentName(!!parentName);
        setModalShow(true);
        formRef.current?.resetFields();
        formRef.current?.setFieldsValue({ parentName, ...record });
    };

    const tableRef = useRef<TableRef>(null);
    const formRef: MutableRefObject<FormInstance<UpdatePermissionReq & { parentName?: string }> | null> = useRef(null);

    const submit = async () => {
        const formData = await formRef.current?.validateFields?.();
        if (!formData) return;
        if (opType === "add") {
            await createPermission(formData as CreatePermissionReq);
            message.success("创建成功");
        }
        if (opType === "edit") {
            await updatePermission({ ...formData, _id: currentRecord.current!._id });
            message.success("编辑成功");
        }
        if (opType === "addChild") {
            const { data } = await createPermission(formData as CreatePermissionReq);
            await updatePermission({ _id: currentRecord.current!._id, children: [...(currentRecord.current?.children || []), data._id] });
            message.success("创建成功");
        }
        if (opType === "clone") {
            const { data } = await createPermission(formData as CreatePermissionReq);
            const parent = getParent();
            if (parent) await updatePermission({ _id: parent._id, children: [...(parent.children || []), data._id] });
            message.success("创建成功");
        }
        tableRef.current?.getList();
        setModalShow(false);
    };

    const searchFormItems: FormItemType[] = [
        { label: "权限名", name: "name" },
        { label: "权限标识", name: "key" },
        { label: "权限类型", name: "type" },
    ];
    const searchParams = useRef<Partial<PermissionType>>({});
    const handleSearch = async (formData: SearchFields) => {
        searchParams.current = formData;
        await tableRef.current?.getList(1, 10);
    };

    const searchFromRef = useRef<FormInstance>();
    const handleReset = () => {
        searchFromRef.current?.resetFields();
        searchParams.current = {};
        tableRef.current?.getList(1, 10);
    };
    const [expandedRowKeys, setExpandedRowKeys] = useState<readonly Key[]>([]);
    const [isAllExpand, setIsAllExpand] = useState(true);
    const getAllParentKeys = () => {
        let keys: Key[] = [];
        const loop = (list: PermissionType[]) => {
            list.forEach(item => {
                if (item.children?.length) {
                    keys.push(item._id);
                    loop(item.children as PermissionType[]);
                }
            });
        };
        loop(permissions.current);
        return keys;
    };
    const toggleExpand = (bol: boolean) => {
        setIsAllExpand(bol);
        setExpandedRowKeys(bol ? getAllParentKeys() : []);
    };
    return (
        <Card
            title={
                <Search<SearchFields>
                    title="权限管理"
                    formItems={searchFormItems}
                    onReset={handleReset}
                    onAdd={handleAdd}
                    onSearch={handleSearch}
                    getFormRef={ref => (searchFromRef.current = ref)}
                    actionMore={
                        <Button onClick={() => toggleExpand(!isAllExpand)} icon={isAllExpand ? <MinusOutlined /> : <PlusOutlined />}>
                            {isAllExpand ? "折叠权限" : "展开权限"}
                        </Button>
                    }
                    createPermission="/system/permission/create"
                    listPermission="/system/permission/list"
                />
            }
        >
            <Table<UpdatePermissionReq>
                ref={tableRef}
                columns={columns}
                getApi={async p => {
                    const { data, ...res } = await getPermissionList({ ...p, ...searchParams.current });
                    permissions.current = data;
                    // setExpandedRowKeys(getAllParentKeys());
                    return { data: { list: data, total: 0 }, ...res };
                }}
                delApi={deletePermission}
                expandable={{ expandedRowKeys, onExpandedRowsChange: (ids: readonly Key[]) => setExpandedRowKeys(ids) }}
                pagination={false}
                actionMore={record => (
                    <Space>
                        <Button type="primary" size="small" icon={<EditOutlined />} onClick={() => clickEdit(record)}>
                            编辑
                        </Button>
                        <Button size="small" icon={<CopyOutlined />} onClick={() => clickClone(record)}>
                            克隆
                        </Button>
                        <Button type="primary" size="small" icon={<FileAddOutlined />} onClick={() => clickAddChild(record)}>
                            添加子权限
                        </Button>
                    </Space>
                )}
                updatePermission="/system/permission/update"
                deletePermission="/system/permission/delete"
            />
            <Modal title={OperationMap[opType]} open={modalShow} onCancel={() => setModalShow(false)} onOk={submit} forceRender>
                <FormByData
                    getFormRef={ref => (formRef.current = ref)}
                    formItems={formatFormItem(columns)}
                    cols={1}
                    formProps={{ initialValues: { status: true } }}
                />
            </Modal>
        </Card>
    );
};

export default Permission;
